<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>SoundManager 2: Javascript Sound for the Web</title>
<meta name="description" content="A javascript MP3 playing sound library (API) using javascript to flash communication providing cross-platform, javascript-driven sound to web pages" />
<meta name="keywords" content="javascript mp3 player, javascript sound, javascript audio, DHTML sound, flash sound, work by Scott Schiller, schillmania, javascript to flash communication" />
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252" />
<link rel="stylesheet" type="text/css" href="demo/demo.css" />
<link rel="stylesheet" type="text/css" href="demo/demo-light.css" />
<script type="text/javascript" src="script/soundmanager2.js"></script>
<script type="text/javascript" src="demo/demo.js"></script>
</head>

<body>

<!--
   SoundManager 2: Javascript Sound for the Web
   http://www.schillmania.com/projects/soundmanager2/

   Copyright (c) 2008, Scott Schiller. All rights reserved.
   Code licensed under the BSD License:
   http://www.schillmania.com/projects/soundmanager2/license.txt

   V2.1.20080331
-->

<div id="site">

 <div id="header">
  <div class="fl speaker"></div>
  <div class="fl">
   <h1>SoundManager 2</h1>
   <h2>Javascript Sound for the Web</h2>
   <p id="version">Version 2.1.20080331</p>
  </div>
  <div class="clear"></div>
 </div>

 <div id="main">
  <h3 id="definition">What is SoundManager?</h3>

  <p><em>(Choose your language)</em></p>

  <ul id="lang-tabs" class="tabs whatis-plain-english">
   <li class="whatis-plain-english"><a href="#whatis-plain-english" title="SoundManager 2 explained, in Plain English" onclick="return chooseLanguage(this)">Plain English</a></li>
   <li class="whatis-web-20-speak"><a href="#whatis-web-20-speak" title="SoundManager 2 explained, in 'Web 2.0-speak'" onclick="return chooseLanguage(this)">Web 2.0-speak</a></li>
  </ul>

  <div id="whatis" class="whatis-plain-english">

   <div id="whatis-plain-english" class="whatis-plain-english">
    <p>SoundManager 2 is a Javascript Sound API which talks to Flash, effectively mapping most of Flash 8's native sound capabilities to Javascript. It enables web developers and front-end engineers to programmatically control sound in a cross-browser/platform way, using a language they already know.</p>
    <p class="last">In short, <em>"It's Javascript Sound for the Web."</em></p>
   </div>

   <div id="whatis-web-20-speak" class="whatis-web-20-speak">
    <p class="disclaimer"><em>(Disclaimer: The following paragraphs are a parody, poking fun at the web 2.0 hype.)</em></p>
    <p><strong>SoundManag<span>R</span> 2.0 Beta<sup>tm</sup></strong> is a social, long-tail-oriented RIA-based enterprise javascript sound platform which leverages streaming AJAX push technology, Web 2.0, and leveraging. Including plenty of ajaxy goodness, this turn-key, SOA-based and Ajax-enhanced platform will take your Rich Enterprise Applications to the next level, connect the dots and move the needle when mashed up with Web 2.0 collective wisdom of the crowd-wowing features such as drag and drop, auto-complete and real-time performance thanks to <a href="http://search.yahoo.com/search?p=enterprise+mashup+server" title="I wish I could say I made this part up..">enterprise mashup servers</a>.</p>
    <p>By leveraging the collective blogosphere and rich folksonomy aspects of the web, it is expected that these supporting technologies may be joining the RIP (Rich Internet Professionals) and DOA (Development Of Asininity) groups within the next few years.<a id="disclaimer" href="#disclaimer" title="[ Apply liberal sarcasm here ] .. Laugh. It's funny." onclick="alert(this.title);return false">*</a></p>
   </div>

  </div>

  <h3 id="demos">Demos</h3>

  <p><em>Less Talk, More Show.</em></p>

  <p>Some examples of Javascript-driven sound, and applications implementing SoundManager 2:</p>
  <div id="sm2-support"><!-- SM2 support warning(s) go here --></div>

  <ul id="demo-list">
   <li><span class="no-debug"><a href="demo/jsAMP-preview/" title="jsAMP demo" onclick="checkDomain(this)">jsAMP MP3 Player Preview Demo</a> |</span> <a href="demo/jsAMP-preview/#debug=1" title="jsAMP demo with debug" onclick="checkDomain(this,true)">jsAMP with debug output</a></li>
   <li><a href="demo/mpc/" title="SoundManager 2 MPC demo" onclick="checkDomain(this)">SoundManager 2 MPC demo</a></li>
   <li class="no-debug"><a href="demo/animation/" title="SoundManager animation demo" onclick="checkDomain(this)">SoundManager 2 animation demo</a></li>
   <li><a href="demo/basic/" title="SoundManager basic demo" onclick="checkDomain(this)">SoundManager 2 basic demo</a> (simple API call examples)</li>
  </ul>

  <h3 id="getting-started">Getting Started</h3>

  <p><em>"I'd like to use this on my site. Where do I start?"</em></p>
  <p>No problem! See this <a href="demo/template/" title="SoundManager 2 template example" onclick="checkDomain(this)">template example</a> which shows the basic requirements of SoundManager 2. (For technical requirements, refer to <a href="#requirements" title="SoundManager 2 requirements">Requirements + Specifications</a>.)</p>
  <p>Like a fine whiskey, SoundManager should come with a disclaimer that reads, "<a href="#responsible-use" title="Don't uglify the web!">Use Responsibly</a>." You should know when to stop, too.</p>

  <h3 id="licensing">Licensing</h3>

  <p>SoundManager 2 is provided free of charge under a <a href="http://www.schillmania.com/projects/soundmanager2/license.txt" title="SoundManager 2 BSD license">BSD license</a>. If you find a nifty or innovative use for it (or just want to comment), <a href="http://www.schillmania.com/content/react/contact/" title="Contact information for Scott Schiller">feedback</a> is always appreciated.</p>

  <h3 id="download">Download</h3>

  <p>See <a href="http://schillmania.com/projects/soundmanager2/" title="SoundManager 2 project home">SoundManager 2 project home</a> for latest version.</p>

<!--
  <p><strong>Current version: 2.1.20080331</strong></p>

  <p class="compact"><a href="http://www.schillmania.com/projects/soundmanager2/download/soundmanagerv21-20080331.zip" title="Download SoundManager 2">SoundManager v2.1.20080331</a> (1.07 MB, .zip)</p>

  <p><em>Includes API, ActionScript source, documentation, examples and demos.</em></p>

  <p class="archive">Archived beta version: <a href="http://www.schillmania.com/projects/soundmanager2/download/soundmanagerv20b-20070415.zip" title="Download archived SoundManager 2">2.0b.20070415</a> (1.07 MB, .zip)</p>
-->

  <h3 id="basic-use">Basic Use</h3>

<div>

  <h4>Adding SoundManager 2 to your page</h4>

  <p>A single Javascript include will link in all of the required code for the library, which will automatically self-initialise after the document has loaded.</p>

  <p>Within <code class="in">&lt;head&gt;</code>:</p>
<pre>&lt;script type="text/javascript" src="<span>soundmanager2.js</span>"&gt;&lt;/script&gt;</pre>

  <p class="in">When ready, SM2 simply calls <code>soundManager.onload()</code> or <code>soundManager.onerror()</code>, methods which you can attach functions to just as with <code>window.onload()</code>.</p>

  <div class="alternate">
   <h4 class="compact">Alternate pre-window.onload() method</h4>
   <p class="in">By default, SM2 will wait until <code>window.onload()</code> before trying to fully initialise. If you wish to start loading the movie before this time, place an inline script node with a single call within <code class="in">&lt;body&gt;</code>, optimally just before <code class="in">&lt;/body&gt;</code>:</p>
<pre>&lt;script type="text/javascript"&gt;<span>soundManager.createMovie();</span>&lt;/script&gt;</pre>
   <p>Alternately, the path to the .swf may be specified, overriding the default:</p>
<pre>&lt;script type="text/javascript"&gt;<span>soundManager.createMovie(<span>'/path/to/soundmanager2.swf'</span>);</span>&lt;/script&gt;</pre>
   <p>In the event an exception occours at this point, SM2 may exit and wait to retry after window.onload().</p>
  </div>

  <p>For a live example of this code, check the <a href="demo/template/" title="SoundManager 2 template example" onclick="checkDomain(this)">template example</a>.</p>

  <h4>Successful Initialisation</h4>

  <p>Once SoundManager has initialised and <code class="in">soundManager.onload()</code> has fired (<a href="#soundmanager-onload" title="SoundManager.onload() handler example">onload() example</a>), sounds may be created, loaded and played in one call using minimal parameters.</p>

  <pre class="code"><code>soundManager.play(<span>'mySound','/path/to/some.mp3'</span>);</code></pre>

  <p>Sounds can also be created without automatically loading or playing, for later use:</p>

  <pre class="code"><code>soundManager.createSound(<span>'myNewSound','/path/to/some.mp3'</span>);</code></pre>

  <p>Once defined, sound objects have methods and properties which can be accessed by the soundManager controller.</p>

<pre class="code"><code>soundManager.play(<span>'myNewSound'</span>);
soundManager.setVolume(<span>'myNewSound',50</span>);
soundManager.setPan(<span>'myNewSound',-100</span>);</code></pre>

  <h4 id="error-handling">Initialisation Failure + Error Handling</h4>

  <p>In the event SoundManager encounters an error during loading, it will silently fail and disable itself; all subsequent calls to the soundManager controller object will return false. If defined, <code class="in">soundManager.onerror()</code> will be called rather than <code class="in">soundManager.onload()</code>. If enabled, debug messages will be written to the browser and/or console.</p>

  <h4>Debugging + Console Support</h4>

  <p class="in">During development, SoundManager may throw custom errors to help debugging. For post-live testing, debug mode can be forced by appending <code>debug=1</code> somewhere in the URL (eg. <code>#debug=1</code> or <code>?debug=1</code>) and refreshing the page. In the event pre-onload() errors are preventing debug messages, <code>debug=alert</code> may serve as a last-effort debugging tool. You may also view some <a href="#debug-output" title="Debug information from SoundManager 2">live debug output</a> on this page.</p>

  <p><em>Supported debug tool/browser consoles:</em></p>
  <ul>
   <li>Firefox, via Firebug (console[log|warn|info|error])</li>
   <li>(Theoretically) any UA supporting console.log(string) natively, including Opera + Safari</li>
  </ul>
  <p class="in">For those browsers without native console support (or when configured to echo to both console and browser), an element with CSS matching <code>div#soundmanager-debug</code> will be created and appended to the document as soon as possible. Messages will be appended in reverse order in-browser to ease reading, with most recent at the top. You may put this element (an empty DIV with the debug ID) in your page's HTML, and can then apply your own CSS to make it look pretty.</p>

  <p>For configuring default debug behaviour, see <a href="#soundmanager-properties" title="SoundManager global properties">SoundManager Global Properties</a>.</p>

  <h4 id="soundmanager-onload">SoundManager onload() Equivalent</h4>
  <p>This is a user-defined onload-style function implemented by SoundManager. Because of the overhead associated in creating and initialising the Flash and Javascript code necessary for SoundManager to function, a separate "onload"-type function is provided so your code can hook into it.</p>
<pre>soundManager.onload = function() {
  <span><span>// soundManager should be ready to use/call at this point</span></span>
  soundManager.createSound(<span>'mySound','/path/to/mysoundfile.mp3'</span>);
  soundManager.play(<span>'mySound'</span>);
}</pre>

  <h4>SoundManager onerror() Equivalent</h4>

  <p>Note also that if SoundManager fails to load, it will call <code class="in">soundManager.onerror()</code> if defined. (onload will not be called given the failure.) You can assign a handler here to be notified of failure, and take appropriate action.</p>
<pre>soundManager.onerror = function() {
  <span><span>// soundManager failed to initialise (security restrictions, no support, missing SWF etc.)</span></span>
  <span><span>// Notify user if needed, disable sound-specific functionality etc.</span></span>
}</pre>

  <h4>SoundManager supported() Convenience Method</h4>

  <p class="in">If you would prefer to call a function to determine the state of SM2 at various times, <code>soundManager.supported()</code> will return a boolean based on 1) An initialisation attempt, and 2) A successful result. This also means that calling <code>supported()</code> <em>prior</em> to SM2's initialisation/onload/onerror process will return false until support has ultimately been determined.</p>

  <h3 id="object-literal-format">Object Literal Format</h3>

  <p>Sounds can be created with instance-specific parameters in an object literal (JSON) format, where omitted parameters inherit default values as defined in soundManager.</p>

<pre>soundManager.createSound({<span>
  id: 'mySound',
  url: '/path/to/some.mp3',
  autoLoad: true,
  autoPlay: false,
  onload: function() {
    alert('The sound '+this.sID+' loaded!');
  },
  volume: 50
</span>});</pre>

</div>

  <p>This object can also be passed as an optional argument to the <code class="in">play</code> method, overriding options set at creation time.</p>

  <p>For a full list of available options, see <a href="#sound-properties" title="SoundManager 2 API info: Sound Properties">Sound Properties Object</a></p>

  <h3 id="soundmanager-api">SoundManager API</h3>

  <p>The following are methods, collections, properties and event handlers provided by the globally-scoped <code class="in">soundManager</code> Javascript object. Both sound properties and methods can be set on a global (inherited) default, or per-sound basis.</p>

  <h4>SoundManager Core Methods</h4>

  <dl>

   <dt><span>object:SMSound </span>createSound(<span>object:options</span>)</dt>
   <dd title="object:options">Creates a sound with an arbitrary number of optional arguments. Returns a <code>SMSound</code> object instance.</dd>
   <dd>
    Example:
<pre><code>soundManager.createSound(<span>{
 id: 'mySound', <span>// required</span>
 url: '/audio/mysoundfile.mp3', <span>// required</span>
 <span>// optional sound parameters here, see <a href="#sound-properties" title="SoundManager 2 API Info: Sound Properties Object">Sound Properties</a> for full list</span>
 volume: 50,
 autoPlay: true,
 whileloading: soundIsLoading <span>// remember to omit comma on the last item</span>
}</span>);</code></pre>
   <p>Each <code>createSound</code> call results in the creation of a <code>SMSound</code> object which stores all properties, methods and events relevant to that particular sound instance.</p>
   <p>Individual sound objects can also easily be referenced as returned from <code>createSound</code>:</p>
<pre><code>var mySoundObject = soundManager.createSound(<span>{
 id: 'mySound',
 url: '/audio/mysoundfile.mp3'
}</span>);
mySoundObject.play(); <span><span>// new SMSound object reference, equivalent to referencing soundManager.getSoundById('mySound')</span></span></code></pre>

   <p>(Note: Code formatting is stylistic, not necessarily recommended.) See <a href="#object-literal-format" title="SoundManager 2 API Info: Sound Properties Object">Object Literal Format</a>.</p>
   </dd>

   <dt>createSound(<span>id:string,url:string</span>)</dt>
   <dd title="id:string,url:string">Creates a sound with the specified ID and URL (simple method.)</dd>
   <dd>Example: <code>soundManager.createSound('<span>mySound</span>','<span>/audio/mysoundfile.mp3</span>');</code></dd>

   <dt>destroySound(<span>id:string</span>)</dt>
   <dd title="id:string">Stops, unloads and destroys a sound specified by ID.</dd>
   <dd>Example: <code>soundManager.destroySound('<span>mySound</span>');</code></dd>
   
   <dt><span>didCreate:boolean</span> play(<span>id:string,[options object]</span>)</dt>
   <dd title="soundID:string">Starts playing the sound specified by ID. (Will start loading if applicable, and will play ASAP.)</dd>
   <dd>Optionally, returns a boolean value indicating "sound created", ie. if the related sound object didn't exist prior to this call and was created to do so.</dd>
   <dd>Example: <code>soundManager.play('<span>mySound</span>');</code></dd>
   <dd>Note that the second parameter, <code>options object</code>, is not required and can take almost any argument from the object literal format (eg. volume.) These should be applied on an instance-specific basis (only overriding existing options for this play instance), but may persist due to an incomplete implementation. (To be fixed.)</dd>
   <dd>Example: <code>soundManager.play('<span>mySound</span>',{<span>volume:50,onfinish:playNextSound</span>});</code></dd>

   <dt>setPosition(<span>id:string,msecOffset:integer</span>)</dt>
   <dd title="id:string,msecOffset:integer">Seeeks to a given position within a sound, specified by miliseconds (1000 msec = 1 second.)</dd>
   <dd>Example: <code>soundManager.setPosition('<span>mySound</span>',<span>2500</span>);</code></dd>
   <dd>Can only seek within loaded sound data, as defined by the <span>duration</span> property.</dd>

   <dt>pause(<span>id:string</span>)</dt>
   <dd title="soundID:string">Pauses the sound specified by ID. (Does not toggle.)</dd>
   <dd>Example: <code>soundManager.pause('<span>mySound</span>');</code></dd>

   <dt>resume(<span>id:string</span>)</dt>
   <dd title="soundID:string">Resumes the currently-paused sound specified by ID.</dd>
   <dd>Example: <code>soundManager.resume('<span>mySound</span>');</code></dd>

   <dt>togglePause(<span>id:string</span>)</dt>
   <dd title="soundID:string">Pauses/resumes play on the sound specified by ID.</dd>
   <dd>Example: <code>soundManager.pause('<span>mySound</span>');</code></dd>

   <dt>setVolume(<span>id:string,volume:integer</span>)</dt>
   <dd title="id:string,volume:integer">Sets the volume of the sound specified by ID. Accepted values: 0-100</dd>
   <dd>Example: <code>soundManager.setVolume('<span>mySound</span>',<span>50</span>);</code></dd>

   <dt>setPan(<span>id:string,volume:integer</span>)</dt>
   <dd title="id:string,volume:integer">Sets the stereo pan (left/right bias) of the sound specified by ID. Accepted values: -100 to 100 (L/R, 0 = center)</dd>
   <dd>Example: <code>soundManager.setPan('<span>mySound</span>',<span>-80</span>);</code></dd>

   <dt>stop(<span>id:string</span>)</dt>
   <dd title="soundID:string">Stops playing the sound specified by ID.</dd>
   <dd>Example: <code>soundManager.stop('<span>mySound</span>');</code></dd>

   <dt>stopAll()</dt>
   <dd>Stops any currently-playing sounds.</dd>
   <dd>Example: <code>soundManager.stopAll();</code></dd>

   <dt>unload(<span>id:string</span>)</dt>
   <dd title="soundID:string">Stops loading the sound specified by ID, canceling any current HTTP request.</dd>
   <dd>Example: <code>soundManager.unload('<span>mySound</span>');</code></dd>
   <dd>Note that SoundManager does this by loading a new, tiny "stub" MP3 file, <code class="in">./data/null.mp3</code>, which replaces the current one from loading. This is defined in the SM2 global object as <code class="in">nullURL</code>, and can be edited.</dd>


<!-- may be buggy, not necessarily needed externally.
   <dt>load(<span>id:string,[options object]</span>)</dt>
   <dd title="soundID:string">Starts loading the sound specified by ID, with options if specified.</dd>
   <dd>Example: <code>soundManager.load('<span>mySound</span>');</code></dd>
   <dd>Example 2: <code>soundManager.load('<span>mySound</span>',{<span>volume:50,onfinish:playNextSound</span>});</code></dd>
-->

   <dt>getSoundById(<span>id:string</span>)</dt>
   <dd title="id:string">Returns an <code>SMSound</code> object specified by ID.</dd>
   <dd>Example: <code>var mySMSound = soundManager.getSoundById('<span>mySound</span>');</code></dd>

   <dt>loadFromXML(<span>xmlURL:string</span>)</dt>
   <dd>Loads and creates sounds as defined in a <a href="http://www.schillmania.com/projects/soundmanager/" title="SoundManager v1 project page">SoundManager v1</a> XML file (legacy)</dd>
   <dd>Note that per-sound options are not supported with this method, and sound objects will be created immediately upon loading and parsing of the XML. The sounds will inherit the <code>defaultOptions</code> settings, with the exception of the <code>stream</code> attribute as set in the XML (true if defined, defaultOption applied if omitted.)</dd>
   <dd>Example: <code>soundManager.loadFromXML('<span>/path/to/some.xml</span>');</code></dd>
   <dd>XML format example: <a href="demo/mpc/acoustic-drumkit.xml">MPC drumkit XML file</a></dd>

   <dt><span>supported:boolean</span> supported()</dt>
   <dd>Returns a boolean indicating whether soundManager has attempted to and succeeded in initialising. This function will return false if called before initialisation has occurred.</dd>
   <dd>Example: <code>soundManager.supported()</code></dd>

  </dl>

  <h4 id="sound-properties">Sound Properties Object</h4>

  <p>The <code class="in">soundManager.defaultOptions</code> object contains parameters which are inherited by default when sounds are made via <code class="in">createSound</code>. They can be overridden on a per-sound basis at create time, or changed dynamically in some cases. Note that none of these options are required when calling <code class="in">createSound</code>, as the defaults will be inherited if unspecified.</p>
  <p><code class="in">soundManager.defaultOptions</code> apply the properties and event handlers as specified above. Defaults are shown below as an example.</p>

<pre><code>soundManager.defaultOptions = <span>{
  'autoLoad': false,             <span>// enable automatic loading (otherwise .load() will be called on demand with .play()..)</span>
  'stream': true,                <span>// allows playing before entire file has loaded (recommended)</span>
  'autoPlay': false,             <span>// enable playing of file as soon as possible (much faster if "stream" is true)</span>
  'onid3': null,                 <span>// callback function for "ID3 data is added/available"</span>
  'onload': null,                <span>// callback function for "load finished"</span>
  'whileloading': null,          <span>// callback function for "download progress update" (X of Y bytes received)</span>
  'onplay': null,                <span>// callback for "play" start</span>
  'whileplaying': null,          <span>// callback during play (position update)</span>
  'onstop': null,                <span>// callback for "user stop"</span>
  'onfinish': null,              <span>// callback function for "sound finished playing"</span>
  'onbeforefinish': null,        <span>// callback for "before sound finished playing (at [time])"</span>
  'onbeforefinishtime': 5000,    <span>// offset (milliseconds) before end of sound to trigger beforefinish..</span>
  'onbeforefinishcomplete': null,<span>// function to call when said sound finishes playing</span>
  'onjustbeforefinish': null,    <span>// callback for [n] msec before end of current sound</span>
  'onjustbeforefinishtime': 200, <span>// [n] - if not using, set to 0 (or null handler) and event will not fire.</span>
  'multiShot': true,             <span>// let sounds "restart" or layer on top of each other when played multiple times..</span>
  'position': null,		 <span>// offset (milliseconds) to seek to within loaded sound data.</span>
  'pan': 0,                      <span>// "pan" settings, left-to-right, -100 to 100</span>
  'volume': 100                  <span>// self-explanatory. 0-100, the latter being the max.</span>
}</span>
</code></pre>

  <p class="alternate"><em>Note</em>: For live examples, see the code behind the <a href="demo/jsAMP-preview/" title="jsMAMP MP3 player demo">jsAMP MP3 Player</a> demo which uses much of this functionality.</p>

  <h4 id="soundmanager-sound-properties">SMSound (Sound Object) Properties</h4>

  <p class="in">Each <code>createSound()</code> call generates a matching <code>SMSound</code> (sound instance) object, which lasts for the life of the page or until explicitly destroyed. Each instance stores stateful information (eg. <code>playState</code>) and provides event handlers for state changes (eg. <code>onload()</code>.)</p>

  <dl>

   <dt>sID</dt>
   <dd>Sound ID string as provided from <code>createSound()</code> or <code>play()</code>.</dd>
   <dd>If an ID is known, the related SMSound object can be retrieved via <code>getSoundById</code> or directly referencing <code>sounds[sID]</code> on the SoundManager global object.</dd>

   <dt>url</dt>
   <dd>The specified URL from which the sound is loaded.</dd>

   <dt>id3</dt>
   <dd>An object literal populated, if applicable, when ID3 data is received (related handler: <code>onid3()</code>)</dd>
   <dd>For property details, see <a href="#onid3" title="onid3() documentation">onid3()</a>.</dd>

   <dt>bytesLoaded</dt>
   <dd>The number of bytes currently received while loading a sound.</dd>

   <dt>bytesTotal</dt>
   <dd>The total number of bytes to be downloaded, while loading a sound.</dd>

   <dt>position</dt>
   <dd>The current location of the "play head" within the sound, specified in milliseconds (1 sec = 1000 msec).</dd>

   <dt>duration</dt>
   <dd>The current length of the sound, specified in milliseconds.</dd>
   <dd>Note that during loading, this property reflects the length of downloaded data, not the full length, until completely loaded (see <a href="#whileloading">whileloading()</a>.) For an approximate "full duration" value while loading, see <code>durationEstimate</code>.</dd>

   <dt>durationEstimate</dt>
   <dd>The estimated duration of the sound, specified in milliseconds.</dd>
   <dd>Due to the dynamic nature of <code>duration</code> while loading, this attempts to provide the full duration by calculating <code>parseInt((self.bytesTotal/self.bytesLoaded)*self.duration)</code> and is updated with each <code>whileloading()</code> interval.</dd>
   <dd>Once the sound has fully loaded, <code>duration</code> should be referenced as it will contain the final and accurate value.</dd>
   <dd>Note that this method works only with Constant Bitrate (CBR)-encoded MP3s due to the consistent data/time assumption. VBR-encoded MP3s will give inaccurate results.</dd>

   <dt>loaded</dt>
   <dd>Boolean value indicating load success as returned from Flash. True indicates success, False is a failure <em>or</em> strangely, a successful load (?) from cache.</dd>
   <dd>Because of the potential for false positives, <code>duration</code> and other properties could be checked as a test of whether sound data actually loaded. For more granular state information, see <a href="#readystate" title="SMSound readyState documentation">readyState</a>.</dd>

   <dt>playState</dt>
   <dd>Numeric value indicating the current playing state of the sound.</dd>
   <dd>0 = stopped/uninitialised</dd>
   <dd>1 = playing <em>or</em> buffering sound (play has been called, waiting for data etc.)</dd>
   <dd>Note that a 1 may not always guarantee that sound is being heard, given buffering and autoPlay status.</dd>

   <dt>paused</dt>
   <dd>Boolean indicating pause status. True/False.</dd>
   <dd>Treat as read-only; use <code>pause()</code>, <code>resume()</code> and <code>togglePause()</code> methods to affect state.</dd>

   <dt id="readystate">readyState</dt>
   <dd>Numeric value indicating a sound's current load status</dd>
   <dd>0 = uninitialised</dd>
   <dd>1 = loading</dd>
   <dd>2 = failed/error</dd>
   <dd>3 = loaded/success</dd>

   <dt>didBeforeFinish</dt>
   <dd>Boolean indicating whether <code>beforeFinish()</code> condition was reached.</dd>

   <dt>didJustBeforeFinish</dt>
   <dd>Boolean indicating whether <code>justBeforeFinish()</code> condition was reached.</dd>

  </dl>

  <h4 id="soundmanager-sound-events">SMSound (Sound Object) Events</h4>

  <p class="in">Not unlike common javascript objects, each SoundManager <code>SMSound</code> (sound instance) object can fire a number of events including <code>onload</code> and others. Functions can be assigned and will be called as needed, and are scoped to the relevant sound object. Specifically, the <code>this</code> keyword will point to the sound object on which the event fired such that its properties can easily be accessed - eg. within an <code>SMSound</code> event handler, <code>this.sID</code> will give the sound ID.</p>

  <dl>

   <dt>onload(<span>boolean:success</span>)</dt>
   <dd>Fires on sound load. Boolean reflects successful load (true), or fail/load from cache (false).</dd>
   <dd>False value should seemingly only be for failure, but appears to be returned for load from cache as well. This seemingly-strange behaviour comes from Flash. More detail may be available from the Flash 8 sound object documentation.</dd>
   <!-- <dd>Example: <code>soundManager.createSound('<span>mySound</span>','<span>/audio/mysoundfile.mp3</span>');</code></dd> -->

   <dt id="whileloading">whileloading()</dt>
   <dd>Fires at a regular interval when a sound is loading and new data has been received. The relevant, updated property is <code>bytesLoaded</code>.</dd>
   <dd>Example handler code: <code>soundManager._writeDebug(<span>'sound '+this.sID+' loading, '+this.bytesLoaded+' of '+this.bytesTotal</span>);</code></dd>
   <dd>Note that the <code>duration</code> property starts from 0 and is updated during <code>whileloading()</code> to reflect the duration of currently-loaded sound data (ie. when a 4:00 MP3 has loaded 50%, the duration will be reported as 2:00 in milliseconds.) However, an estimate of final duration can be calculated using <code>bytesLoaded</code>, <code>bytesTotal</code> and <code>duration</code> while loading. Once fully-loaded, <code>duration</code> will reflect the true and accurate value.</dd>

   <dt>onplay()</dt>
   <dd>Fires when <code>sound.play()</code> is called.</dd>

   <dt>whileplaying()</dt>
   <dd>Fires at a regular interval when a sound is playing, and a position (time) change is detected. The relevant, updated property is <code>position</code>.</dd>
   <dd>Example handler code: <code>soundManager._writeDebug(<span>'sound '+this.sID+' playing, '+this.position+' of '+this.duration</span>);</code></dd>

   <dt>onstop()</dt>
   <dd>Fires when <code>sound.stop()</code> is explicitly called. For natural "sound finished" <code>onfinish()</code> case, see below.</dd>

   <dt>onfinish()</dt>
   <dd>Fires when a playing sound has reached its end. By this point, relevant properties like <code>playState</code> will have been reset to non-playing status.</dd>

   <dt>onbeforefinishcomplete()</dt>
   <dd>Fires when a sound has finished, <code>onfinish()</code> has been called, but before the sound play state and other meta data (position, etc.) are reset.</dd>

   <dt>onbeforefinish()</dt>
   <dd>Fires when a playing, fully-loaded sound has reached <code>onbeforefinishtime</code> (eg. 5000 msec) from its end.</dd>

   <dt>onjustbeforefinish()</dt>
   <dd>Fires approximately <code>justbeforefinishtime</code> before the end of a fully-loaded, playing sound.</dd>
   <dd>This is based on a polling approach given SM2 must track the sound's position, and is approximated (eg. a 200 msec value may fire at 187 msec before the end of the sound.)</dd>

   <dt id="onid3">onid3()</dt>
   <dd>Fires when ID3 data has been received. Relevant property is <code>id3</code>, which is an object literal (JSON)-style object. Only fields with data will be populated.</dd>
   <dd>Note that ID3V2 data is located at the beginning (header) of an MP3 file and will load almost immediately, whereas ID3V1 data is at the end and will not be received until the MP3 has fully loaded.</dd>
   <dd>
     Example handler code:
    <div><pre>
<code>soundManager._writeDebug(<span>'sound '+this.sID+' ID3 data received'</span>);
var prop = null;
var data = '';
for (prop in this.id3) {
  data += prop+': '+this.id3[prop]+','; <span>// eg. title: Loser, artist: Beck</span>
}</code></pre>
    </div>
   </dd>
   <dd>Refer to the <a href="http://livedocs.adobe.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&amp;file=00002676.html" title="Flash 8 Sound.id3 property documentation">Flash 8 Sound.id3</a> documentation for a list of ID3 properties.</dd>
   <dd>When parsing ID3 data, it is best to check for the existance of ID3V1 data first, and apply ID3V2 if no matching ID3V1 data is defined. (V1 should "inherit" from V2, ideally, if available.)</dd>

  </dl>

  <h4 id="soundmanager-sound-methods">SMSound (Sound Object) Methods</h4>

  <p class="in">SoundManager provides wrappers for all SMSound methods - eg. <code>soundManager.play('<span>mySound</span>')</code> checks for a valid sound object, and then calls <code>soundManager.sounds['<span>mySound</span>'].play()</code> on that particular object.</p>
  <p>The following methods can be called directly on a SMSound instance. The method calls are the same as the SoundManager global methods documented above for existing sound objects, minus the sound ID parameter.</p>

  <dl>

   <dt>play(<span>[options object]</span>)</dt>
   <dt>setPosition(<span>msecOffset:integer</span>)</dt>
   <dt>pause()</dt>
   <dt>resume()</dt>
   <dt>togglePause()</dt>
   <dt>setVolume(<span>volume:integer</span>)</dt>
   <dt>setPan(<span>pan:integer</span>)</dt>
   <dt>stop()</dt>
   <dt>unload()</dt>

  </dl>


  <h4 id="soundmanager-properties">SoundManager Global Properties</h4>

  <p>SoundManager includes a few global parameters which configure debug mode, flash movie path and other behaviours.</p>

<pre><code><span>soundManager.url = '/path/to/soundmanager2.swf';
soundManager.debugMode = true;    <span>  // enable debugging output (div#soundmanager-debug, OR console..)</span>
soundManager.useConsole = true;   <span>  // use firebug/safari console.log()-type debug console if available</span>
soundManager.consoleOnly = false; <span>  // if console is being used, do not create/write to #soundmanager-debug</span>
soundManager.allowPolling = true; <span>  // allow flash to poll for status update..</span>
soundManager.nullURL = '/null.mp3'; <span>// URL of silent/blank MP3 to use when unloading/canceling a loaded/loading sound</span>
</span></code></pre>

  <p>To modify global SoundManager defaults, edit the main soundmanager2.js file (look for above section in code) or assign new values in your own application script before <code class="in">window.onload()</code> fires.</p>
  <p>Example per-application override:</p>
<pre><code><span>soundManager.debugMode = false;          <span>// disable debug mode</span>
soundManager.defaultOptions.volume = 33; <span>// set global default volume</span>
</span></code></pre>

  <h4>SoundManager Core Events</h4>

  <p class="in">The following events are attached to the <code>soundManager</code> global object and are useful for detecting the success/failure of the API's initialisation.</p>

  <dl>
   <dt title="object:function">onload()</dt>
   <dd>Function called when SoundManager has successfully loaded.</dd>
   <dd>Example: <code>soundManager.onload = <span>function() { alert('SoundManager ready to use'); }</span></code></dd>
   <dd>Once this function has been called, all core methods will be available to use.</dd>
   <dd>Note that <code>onload()</code> is not called when SoundManager fails to load; instead, <code>onerror()</code> is called.</dd>
   <dt title="object:function">onerror()</dt>
   <dd>Function called when SoundManager fails to successfully load and/or initialise.</dd>
   <dd>Example: <code>soundManager.onerror = <span>function() { alert('SoundManager failed to load'); }</span></code></dd>
   <dd>This handler will be called if there are security restrictions preventing Javascript from talking to Flash, a missing .swf file, lack of browser support, or other exceptions that fire when the initialisation function is called.</dd>
  </dl>

  <h4>SoundManager Object Collections</h4>

  <dl>
   <dt title="object:array">soundIDs[]</dt>
   <dd>An array of sound ID strings, ordered by creation. Can be used to iterate through <code>sounds{}</code> by ID.</dd>
   <dt title="object:array">sounds{}</dt>
   <dd>An object literal/JSON-style instance of <code>SMSound</code> objects indexed by sound ID (as in <code>sounds['mySound']</code> or <code>sounds.mySound</code>), used internally by SoundManager. <code>soundManager.getSoundById()</code> may be used as an alternate to directly accessing this object.</dd>
  </dl>

  <h3 id="requirements">Requirements + Specifications</h3>

  <h4>Prerequisites (client)</h4>

  <ul>
   <li>Flash plugin, version 8 or higher</li>
   <li>Supported Browser</li>
  </ul>

  <h4>Supported Browsers/Platforms</h4>

  <p>Javascript-to-flash communication is possible through Flash 8's ExternalInterface feature, which (as I understand) uses a standard browser plugin architecture implemented by each browser manufacturer (see <a href="http://www.mozilla.org/projects/plugins/npruntime.html" title="Mozilla plugin scripting reference">NPAPI</a>.) As a result, the following browsers should be supported:</p>

  <ul>
   <li>IE 5.0+, Win32</li>
   <li>Netscape 8.0+, Windows/Mac</li>
   <li>Mozilla 1.7.5+, Windows/Mac</li>
   <li>Firefox 1.0+, Windows/Mac</li>
   <li>Firefox 1.5+, Linux (Flash 9 beta)</li>
   <li>Safari 1.3+, Mac</li>
   <li>Opera 9.10+, Windows</li>
  </ul>

  <p>For reference, see Adobe's <a href="http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&amp;file=00002200.html" title="Adobe ExternalInterface notes">ExternalInterface support page</a> which documents supported browsers.</p>

  <p>At this time, not all combinations of browser/OS have been tested. Some unlisted configurations may be supported, but have not been explicitly verified to work.</p>

  <h4>Unsupported Configurations</h4>

  <p>The following browser/OS combinations have been reported as buggy, or may be unsupported:</p>

  <ul>
   <li>Konqueror (version unknown)</li>
  </ul>

  <h3 id="caveats">Caveats + Limitations / FAQ</h3>

  <h4>Supported sound format (MP3-only, with caveats)</h4>
  <p>SM2 uses Flash's native Sound object for loading and managing sound, so it is subject to the same limitations that Flash 8 is. Perhaps a design decision, the Flash 8 sound object only supports MP3 files through the <code class="in">loadSound()</code> ActionScript method. SM2 is not able to load other sound formats, including audio-only SWF files, due to this limitation. Refer to the <a href="http://livedocs.macromedia.com/flash/8/main/00002668.html" title="Info on Flash 8's sound object">Flash 8 sound object documentation</a> for details.</p>

  <h4>MP3 Format Caveats</h4>
  <p>Additionally, some very low and very high bitrate MP3s, and Variable Bitrate (VBR) MP3s may play either too quickly or too slowly (see <a href="http://www.boutell.com/newfaq/creating/chipmunk.html" title="Flash mp3 chipmunk problem description">"the chipmunk problem"</a>); if you are encountering this issue, try re-encoding at a different bitrate (between 64 kbps and 192 kbps, for example.) Using Constant Bitrate (CBR) encoding may also alleviate this problem.</p>
  <p>It has been suggested that sample rates that are neither 22/44 KHz can also contribute to this issue.</p>

  <h4>Looping + multi-shot (overlaying)</h4>
  <p class="in">Perhaps due to the way Flash dynamically loads and decodes MP3 data, seamless looping doesn't seem to be fully implemented. Loops have a noticeable gap between the finish and start. This has been an issue since the original version of SoundManager. Rather than have a broken feature, the funcionality has been omitted until a solid workaround is found.</p>
  <p class="in">Regarding overlaying, even though a multi-shot option can be specified, it does not work in practice; a single instance of a sound can only have one timeline. The current behaviour is that when <code>multiShot</code> is specified and <code>play()</code> is called on a currently-playing sound, it will restart from the beginning without an overlay.</p>
  <p>However, the API does provide some creative ways (<code class="in">onbeforefinish</code> for looping, multiple sound objects for multi-shot layering) of working around these Flash limitations.</p>
  <p>It should be noted that sounds can loop seamlessly and be layered when linked and exported to SWF from within the Flash IDE, but SoundManager does not support SWF-based audio.</p>

  <h4>ID3 Parsing</h4>
  <p>ID3 data can differ in formatting, version and subsequently be oddly-parsed by Flash. Values may sometimes be repeated across different fields.</p>
  <p>ID3 info seems to fail to load for iTunes 7-edited files, perhaps due to the format or inclusion of album artwork (image data)</p>

  <h4>Performance Notes: Caching + RAM Obeservations</h4>
  <p>Flash appears to use the browser cache (presumably the OS' native, or closest browser,) so the browser's cache size and other settings may affect Flash's cache behaviour. It is safe to assume a 100 MB MP3 will probably not be cached, for example, but a 16 MB one most likely will be.</p>
  <p>MP3s appear to be loaded and stored in RAM while loading over HTTP, so memory use needs to be considered for both large MP3s and streaming radio-type applications.</p>

  <h4>Timing (JS + Flash, ExternalInterface-related)</h4>
  <p>Javascript-to-Flash communication is not instantaneous on slower systems, but feels much more near real-time on more modern systems. "Lag" can be noted in some cases from function call to sound execution. It is possible some performance analysis can help to speed up this area for timing-critical applications involving animation etc., but this area has not been thoroughly investigated yet. Brad Neuberg has some notes on <a href="http://codinginparadise.org/weblog/2006/02/how-to-speed-up-flash-8s.html" title="Brad Neuberg - How To Speed Up ExternalInterface">speeding up ExternalInterface</a> which may be relevant.</p>

  <h3 id="revision-history">Revision History</h3>

  <ul class="compact">

   <li>

    <h4>V2.1.20080331 (current)</h4>
    <p class="compact">The latest and greatest. (<a href="#download" title="Go to Download section">download</a>)</p>
    <p><em>Changelog</em>:</p>
    <ul class="tight nested">
     <li class="in">Modified <code>createSound()</code> to return a sound object if successful (more logical)</li>
     <li class="in">Updated <code>setPosition()</code> method and added <code>position</code> option parameter, documentation + demo (bugfix)</li>
     <li class="in">Corrected <code>createSound()</code> and <code>play()</code> sound option inheritance/overriding behaviour (eg. <code>position</code>) to work as expected (most to least important: Method call options -&gt; sound object instance options -&gt; SM2 global options)</li>
     <li class="in">Updated <code>deleteSound()</code> so Array.splice() is used instead of delete, the latter doesn't cause Array.length to update (bugfix)</li>
     <li>Modified debug=alert to only work when debug mode is enabled (potential annoyance aversion)</li>
     <li class="in">Modified <code>togglePause()</code> to use <code>position</code> option parameter rather than undocumented <code>offset</code> (oops :D)</li>
     <li class="in">Added <code>supported()</code> convenience method (indicates pass/fail after SM2 has initialised.)</li>
     <li>Added disabling debug calls from Flash (performance)</li>
     <li>Added URL hash updating/bookmarking and page title updating to jsAMP demo app</li>
     <li>Updated project page layout</li>
    </ul>

    <h4>V2.0b.20070415</h4>
    <p><em>Changelog</em>:</p>
    <ul class="tight nested">
     <li class="in">Added <code>destroySound()</code> method</li>
     <li>Made debug output slightly less-verbose (commented out)</li>
     <li>Safety tweak for position-related Flash bug when loading new sounds</li>
     <li class="in">Highly-expanded documentation (<code>SMSound</code> events + properties, examples, caveats, FAQs etc.)</li>
     <li>Added time-sensitive light/dark theme for documentation</li>
    </ul>

    <h4>V2.0b.20070201</h4>
    <p class="compact">Second beta?</p>
    <p><em>Changelog</em>:</p>
    <ul class="tight nested">
     <li>Fixed stopAll() bug (previously broken)</li>
     <li>Added <code class="in">nullURL</code> parameter</li>
     <li>Updated documentation</li>
    </ul>
    <h4>V2.0b.20070123</h4>
    <h4>V2.0b.20070118</h4>
    <h4>V2.0b.20070115</h4>
   </li>

   <li>
    <h4>V2.0b.20070107</h4>
    <p class="compact">First beta</p>
   </li>

   <li>
    <h4>V2.0a.20060904</h4>
    <p class="compact">Prerelease alpha</p>
   </li>

  </ul>

  <h3 id="responsible-use">"Use Responsibly"</h3>
  <h4>A Word Of Vice</h4>
  <p>Not every button, link, element or paragraph on the web needs to zoom, move, change colour <em>and</em> be noisy, repetitive and annoying all at the same time. Use your own discretion! :)</p>

  <h3>Demo Credits</h3>

  <h4>Background Tile</h4>
  <p class="compact">Modified from <a href="http://www.squidfingers.com/" title="Squidfingers' site" rel="nofollow">squidfingers.com</a> (free patterns)</p>

  <h4>Sound Sources</h4>
  <p class="compact">MPC Demo Sounds downloaded from <a href="http://www.akai.com/" title="AKAI, MPC/electronics manufacturer" rel="nofollow">AKAI.com</a></p>
  <p class="compact">Theme switch SFX from user <a href="http://freesound.iua.upf.edu/samplesViewSingle.php?id=33462" title="'button23.wav' sample page" rel="nofollow">pempi</a>, freesoundproject (Creative Commons Sampling Plus 1.0 License)</p>
  <p class="compact">Tab switch SFX from user <a href="http://freesound.iua.upf.edu/samplesViewSingle.php?id=407" title="'click 1 off click.wav' sample page" rel="nofollow">TicTacShutUp</a>, freesoundproject (Creative Commons Sampling Plus 1.0 License)</p>

  <h3 id="general">General</h3>
  <p>SoundManager was written to meet a desire to have Javascript-driven sound for interactive web-based projects. It is free for use in both personal and commercial projects (see <a href="#licensing" title="SoundManager 2 licensing information">Licensing</a>.) It was originally developed for personal use and has been packaged with the hopes of being useful to others.</p>
  
  <h3 id="related-projects">Related Projects</h3>
  <h4>JavaScript/DHTML/Flash MP3 players</h4>
  <p>If you're searching for an included/embedded-type media player, these related projects might of use.</p>
  <ul>
   <li><a href="http://developer.yahoo.com/mediaplayer/" title="An embedded player that supports a number of sound formats" rel="nofollow">Yahoo! Media Player</a> supports a number of different formats depending on your system's configuration, and can display artist / album information and so on.</li>
   <li><a href="http://jssoundkit.sourceforge.net/" title="A Javascript/Flash MP3 player" rel="nofollow">JSSoundkit</a>, an MP3 player with a simple UI.</li>
  </ul>

  <h3 id="external-links">Links</h3>
  <ul>
   <li><a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 Web Home">SoundManager 2 Project Page</a> (schillmania.com)</li>
   <li><a href="http://livedocs.macromedia.com/flash/8/main/00002668.html" title="Info on Flash 8's sound object">Flash 8 sound object documentation</a> (livedocs.macromedia.com)</li>
  </ul>

  <h3 id="sonundmanager-about">About</h3>
  <p><a href="http://www.schillmania.com" title="Scott Schiller's experimental design site">Scott Schiller</a> (<a href="http://www.schillmania.com/content/react/contact/" title="Contact information for Scott Schiller">contact</a>) is a Front-end Engineer (previously "Web Developer") who builds fun creative and technical stuff on the web - or failing that, tries - when he has free time. He likes building cool things which contribute to, yet enjoys mocking, the <a href="http://www.schillmania.com/content/opinion/2005/10/dont-believe-the-web-20-hype/" title="Web 2.0: Don't Believe The Hype!">Web 2.0 meme</a>. (See <a href="http://www.schillmania.com/content/entries/2006/08/how-web20-aware-are-you/" title="Take the Web 2.0 Awareness Test!">How Web 2.0-Aware Are You?</a>)</p>

  <h3 id="debug-output">Debug Output</h3>
  <p>Live debug info from SoundManager 2, active on this page for demo tests.</p>
  <p>If you're seeing errors here or in demos, this info can help in troubleshooting.</p>
  <div id="soundmanager-debug"></div>

 </div>

 <a href="#" onclick="toggleTheme();return false" title="Toggle theme" class="theme">*</a>

</div>

<script type="text/javascript">soundManager.createMovie();</script>

<!-- counter stuff, if loading from live site.. -->
<script type="text/javascript" src="http://include.reinvigorate.net/re_.js"></script>
<script type="text/javascript">doStats();</script>
</body>

</html>
